#pragma once
#include<iostream>
#include<string>
#include<unistd.h>
#include<queue>
#include<pthread.h>

namespace ns_thread_pool{
    const int g_num = 5;
    template<class T>
    class Thread_pool{
    private:
        int num_;//线程数
        std::queue<T> task_queue;//任务队列，临界资源

        pthread_mutex_t mtx;
        pthread_cond_t cond;
    public:
        Thread_pool(int num = g_num) : num_(num){
            pthread_mutex_init(&mtx, nullptr);
            pthread_cond_init(&cond, nullptr);
        }
        // 在类中要让线程执行类内成员方法是不可行的。
        // 只能让线程执行静态方法,静态成员方法是没有this指针的，也没有办法访问的非静态成员
        static void* Rountine(void* args){
            pthread_detach(pthread_self());//线程分离
            Thread_pool<T>* tp = (Thread_pool<T>*)args;
            while(true){
                tp->Lock();
                while(tp->IsEmpty()){//任务队列为空
                    tp->wait();
                }
                //任务队列中一定有任务了
                T t;
                tp->PopTask(&t);
                tp->UnLock();

                t();
            }
        }
        void InitThreadPool(){
            pthread_t tid;
            for(int i = 0; i < num_; i++){
                pthread_create(&tid, nullptr, Rountine, (void*)this);
            }
        }
        void Lock(){
            pthread_mutex_lock(&mtx);
        }
        void UnLock(){
            pthread_mutex_unlock(&mtx);
        }
        bool IsEmpty(){
            return task_queue.empty();
        }
        void wait(){
            pthread_cond_wait(&cond, &mtx);
        }
        void WakeUp(){
            pthread_cond_signal(&cond);
        }
        void PushTask(const T& in){
            Lock();
            task_queue.push(in);
            UnLock();
            WakeUp();
        }
        void PopTask(T* out){
            *out = task_queue.front();
            task_queue.pop();
        }
        ~Thread_pool(){
            pthread_mutex_destroy(&mtx);
            pthread_cond_destroy(&cond);
        }
    };
}
